<template>
  <!-- 
    :unmount-on-close="false"
    是否在关闭时卸载弹出框节点 存在容器高度破坏 bug
    当卸载节点之后，表格重新加载数据之后 无法选中已选数据
   -->
  <a-popover
    :popup-visible="isPopup"
    trigger="focus"
    :style="getPopoverWidth"
    position="bl"
    content-class="tableSelectPopover"
  >
    <a-input-tag
      ref="inputTagRef"
      allow-clear
      v-model="selectValue"
      :field-names="{
        label: props.labelField,
        value: props.valueField,
      }"
      @focus="isPopup = true"
      :placeholder="props.placeholder"
      :style="getWidth"
      @remove="removeInputTag"
      @clear="clearInputTag"
      @change="changeInputTag"
    />
    <template #content>
      <div ref="popoverContentRef">
        <BasicForm
          v-if="props.formProps.schemas"
          @reset="handleFormReset"
          @register="register"
          @submit="handleFormSubmit"
        />
        <BasicTable
          ref="basicTableRef"
          v-bind="getTableProps"
          :pagination="{ simple: true }"
          :showTableSetting="false"
          :isKeepRowKeys="true"
          :rowSelection="getRowSelection"
          @select="tableSelect"
          @select-all="tableSelectAll"
          @fetch-success="tableFetchSuccess"
        />
      </div>
    </template>
  </a-popover>
</template>

<script lang="ts" setup>
  import { ref, computed, nextTick, watch } from 'vue';
  import { BasicTable } from '../index';
  import { TableSelectProps } from './props';
  import { onClickOutside } from '@vueuse/core';
  import { BasicForm, useForm } from '@/components/Form/index';
  import { cloneDeep } from 'lodash-es';

  const isPopup = ref(false);
  const basicTableRef = ref();
  const selectValue = ref<any[]>([]);
  const returnData = ref<any>([]);
  const tableDataMap = ref<object>({});
  const popoverContentRef = ref();

  const props = defineProps({
    ...TableSelectProps,
  });

  const emit = defineEmits([
    'press-enter',
    'clear',
    'remove',
    'change',
    'update:value',
    'form-values-change',
  ]);

  watch(
    () => props.value,
    () => {
      selectValue.value = props.value;
    },
    {
      immediate: true,
      deep: true,
    },
  );

  const getPopoverWidth = computed(() => {
    return {
      width: props.popoverWidth,
    };
  });

  const getWidth = computed(() => {
    return {
      width: props.width,
    };
  });

  const getTableProps = computed(() => {
    return props.tableProps;
  });

  const getRowSelection = computed(() => {
    return {
      type: props.multiple ? 'checkbox' : 'radio',
      showCheckedAll: !!props.multiple,
      selectedRowKeys: selectValue.value,
      checkStrictly: true,
    };
  });

  const [register, { getFieldsValue }] = useForm({
    ...props.formProps,
  });

  function handleFormSubmit(values: Recordable) {
    emit('form-values-change', values);
    basicTableRef.value.reload(values);
  }

  function handleFormReset() {
    emit('form-values-change', getFormValues());
    basicTableRef.value.reload();
  }

  function removeInputTag() {
    // isPopup.value = false;
    emit('remove', selectValue.value);
    emit('update:value', selectValue.value);
  }

  function clearInputTag() {
    isPopup.value = false;
    emit('clear', selectValue.value);
    emit('update:value', selectValue.value);
  }

  function changeInputTag() {
    nextTick(() => {
      emit('change', selectValue.value);
      emit('update:value', selectValue.value);
    });
  }

  // 表格原始数据列表
  const getTableData = computed(() => {
    return cloneDeep(basicTableRef.value?.getDataSource() || []);
  });

  // 表格数据加载完成
  function tableFetchSuccess() {
    const list = getTableData.value;
    const key = props.valueField;
    list.forEach((item) => {
      if (!tableDataMap.value[item[key]]) {
        tableDataMap.value[item[key]] = item;
      }
    });
  }

  function findKeysData(values) {
    const newList: any[] = [];
    values.forEach((item) => {
      tableDataMap.value[item] && newList.push(tableDataMap.value[item]);
    });
    return newList;
  }

  function tableSelect(keys) {
    returnData.value = !keys.length ? [] : findKeysData(keys);
    selectValue.value = returnData.value;
    const reData = getReData(returnData.value);
    if (!props.multiple) {
      isPopup.value = false;
    }
    emit('change', reData);
    emit('update:value', selectValue.value);
  }

  function getReData(value) {
    return props.multiple ? value : value.length ? value[0] : null;
  }

  function tableSelectAll(status) {
    const allValues = status ? getTagAllValues() : [];
    selectValue.value = allValues.map((item) => {
      return item[props.valueField];
    });
  }

  function getTagAllValues() {
    const tableList = basicTableRef.value?.getDataSource();
    return tableList.map((item) => {
      return {
        ...item,
      };
    });
  }

  function getDataSource() {
    return basicTableRef.value?.getDataSource();
  }

  function getFormValues() {
    return getFieldsValue();
  }

  onClickOutside(popoverContentRef, (event: any) => {
    // 暂且兼容一下 onClickOutside 方法并没有考虑这种场景
    if (event.target?.className === 'arco-select-option-content') return;
    isPopup.value = false;
  });

  defineExpose({
    getDataSource,
    getTagAllValues,
    getFormValues,
  });
</script>

<style lang="less"></style>
